import Koa from 'koa';
import {isFunction, isObjectLike} from 'lodash';
import Router from 'koa-router';
import dirs from 'require-dir';
import cors from 'koa2-cors';
import cmd from './cmd';
import log from './log';
import cfg from './cfg';
import {error, ext} from './util/koa-ext';
import jwt from './util/koa-jwt';
import schedules from './schedules';
import * as redis from './redis';

//初始化redis
redis.init();

const app = new Koa();
const convert = require('koa-convert');

// 统一转换旧版本的中间件
const use = app.use;
app.use(cors());
app.use = x => use.call(app, convert(x));

// 错误处理
app.use(error({log}));

// 日志记录
if (cfg.dev) {
    app.use(require('koa-logger')());// eslint-disable-line
} else {
    app.use(require('koa-log4js')());// eslint-disable-line
}

// 静态文件
if (cfg.root) {
    // 前端刷新
    //eslint-disable-next-line
    app.use(async(ctx, next) => {
        // 对于非api非文件的GET请求视为刷新前端路由
        if (ctx.method === 'GET' &&
            ctx.path.indexOf('.') < 0 &&
            ctx.path !== cfg.api && !ctx.path.startsWith(cfg.apiPrefix)) {
            // 后台只需返回主页
            ctx.path = cfg.index;
        }
        await next();
    });

    // eslint-disable-next-line
    app.use(require('koa-static-cache')(
        cfg.root,
        cfg.file,
    ));
}

// 内容解析
// eslint-disable-next-line
app.body = convert(require('koa-body')({
    ...cfg.body,
    patchNode: true,
    // formidable: {uploadDir: __dirname},
    multipart: true,
}));

app.use(app.body);

// JSON调试
if (cfg.dev) {
    app.use(require('koa-json')());// eslint-disable-line
}

// 身份认证
if (cfg.auth) {
    const secret = cfg.auth;
    app.auth = jwt({secret});
    app.secret = secret;
}

// 功能扩展
app.use(ext({log}));

// 路由定义
function loadRoutes(routes, uri) {
    // eslint-disable-next-line
    for (const name in routes) {
        if (name === 'db' || name === 'data' || name === 'core') {
            continue;
        }
        const route = routes[name];
        let obj = route;
        if (!isFunction(obj)) { //默认文件夹式路由
            obj = obj.index;
        }
        if (obj && isFunction(obj)) {
            const r = new Router();
            const prefix = `${uri}${name === 'index' ? '' : `/${name}`}`;
            const noAuth = obj(r, app);
            const router = new Router();
            if (!noAuth && app.auth) {
                router.use(app.auth);
            }
            router.use(prefix, r.routes());
            app.use(router.routes());
            log.debug(`+ ${prefix}`);
        } else if (isObjectLike(route)) {
            loadRoutes(route, `${uri}/${name}`);
        }
    }
}

const rs = dirs('./api', {recurse: true});
loadRoutes(rs, cfg.api);

// 启动服务
const server = app.listen(cmd.port || cfg.port, cfg.host, (err) => {
    if (err) {
        log.error(err);
    } else {
        log.info('started at', server.address().port);
    }
});

//定时任务初始化
schedules();
